import java.util.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;

，class Record {
    String date;     //日期
    double amount;   //金额
    String category;  //种类
    String remark;   //备注

    //构造方法创建对象
    public Record(String date, double amount, String category, String remark) {
        this.date = date;
        this.amount = amount;
        this.category = category;
        this.remark = remark;
    }

    @Override
    public String toString() {
        return "日期: " + date + ", 金额: " + amount + ", 类别: " + category + ", 备注: " + remark;
    }
}

class FinanceTracker {
    private ArrayList<Record> incomeRecords = new ArrayList<>();
    private ArrayList<Record> expenseRecords = new ArrayList<>();
    private Scanner scanner = new Scanner(System.in);
    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    public static void main(String[] args) {
        FinanceTracker manager = new FinanceTracker();
        manager.showMenu();
    }

    //菜单
    public void showMenu() {
        while (true) {
            System.out.println("=================================");
            System.out.println("欢迎使用个人账单管理系统");
            System.out.println("请选择操作：");
            System.out.println("1. 记录收入");
            System.out.println("2. 记录支出");
            System.out.println("3. 查看所有账单");
            System.out.println("4. 查询账单");
            System.out.println("5. 设置月度预算");
            System.out.println("6. 查看月度统计报告");
            System.out.println("7. 退出系统");
            System.out.print("请输入选项序号：");
            int option = scanner.nextInt();
            scanner.nextLine(); // 清除缓冲区

            switch (option) {
                case 1:
                    recordIncome();
                    break;
                case 2:
                    recordExpense();
                    break;
                case 3:
                    viewAllRecords();
                    break;
                case 4:
                    queryRecords();
                    break;
                case 5:
                    setMonthlyBudget();
                    break;
                case 6:
                    viewMonthlyReport();
                    break;
                case 7:
                    System.out.println("感谢使用，系统已退出。");
                    return;
                default:
                    System.out.println("无效的选项，请重新输入。");
            }
        }
    }
    //记录收入
    private void recordIncome() {
        System.out.println("请输入收入信息：");
        String date = getDateInput();
        double amount = getPositiveAmount("金额：");
        System.out.print("类别（如工资、奖金等）：");
        String category = scanner.nextLine();
        System.out.print("备注：");
        String remark = scanner.nextLine();

        incomeRecords.add(new Record(date, amount, category, remark));
        System.out.println("收入已成功记录！");

    }


    //记录支出
    private void recordExpense() {
        System.out.println("请输入支出信息：");
        String date = getDateInput();
        double amount = getPositiveAmount("金额：");
        System.out.print("类别（如餐饮、交通、购物等）：");
        String category = scanner.nextLine();
        System.out.print("备注：");
        String remark = scanner.nextLine();

        expenseRecords.add(new Record(date, amount, category, remark));
        System.out.println("支出已成功记录！");

    }

    private String getDateInput() {
        while (true) {
            System.out.print("日期（YYYY-MM-DD）：");
            String date = scanner.nextLine();
            if (isValidDate(date)) {
                return date;
            } else {
                System.out.println("日期格式无效，请重新输入。");
            }
        }
    }

    private boolean isValidDate(String date) {
        try {
            dateFormat.parse(date);
            return true;
        } catch (ParseException e) {
            return false;
        }
    }

    double getPositiveAmount(String prompt) {
        double amount = -1;
        while (amount < 0) {
            System.out.print(prompt);
            amount = scanner.nextDouble();
            scanner.nextLine(); // 清除缓冲区
            if (amount < 0) {
                System.out.println("金额必须为正数，请重新输入。");
            }
        }
        return amount;
    }

    //查看账单
    private void viewAllRecords() {
        for (Record t : incomeRecords ) {
            System.out.println("---- 收入记录 ----");
            System.out.println("日期"+t.date + "金额" + t.amount + "类别" + t.category + "备注" + t.remark);
        }


        System.out.println("---- 支出记录 ----");
        for (Record t  :expenseRecords) {
            System.out.println("日期"+t.date + "金额" + t.amount + " 类别" + t.category + "备注" + t.remark);
        }
    }
    //查询账单
    private void queryRecords() {
        System.out.println("请输入查询类别（收入/支出）：");
        String categoryType = scanner.nextLine();
        System.out.println("请选择查询条件：");
        System.out.println("1. 按日期查询");
        System.out.println("2. 按日期范围查询");
        System.out.println("3. 按类别查询");
        int condition = scanner.nextInt();
        scanner.nextLine(); // 清除缓冲区

        switch (condition) {
            case 1:
                System.out.print("请输入日期 (yyyy-MM-dd)：");
                String date = scanner.nextLine();
                queryByDate(categoryType, date);
                break;
            case 2:
                System.out.print("请输入开始日期 (yyyy-MM-dd)：");
                String startDate = scanner.nextLine();
                System.out.print("请输入结束日期 (yyyy-MM-dd)：");
                String endDate = scanner.nextLine();
                queryByDateRange(categoryType, startDate, endDate);
                break;
            case 3:
                System.out.print("请输入类别：");
                String category = scanner.nextLine();
                queryByCategory(categoryType, category);
                break;
            default:
                System.out.println("无效的查询条件，请重新选择。");
        }
    }

    // 按日期查询账单
    private void queryByDate(String categoryType, String date) {
        try {
            Date queryDate = dateFormat.parse(date);
            if ("收入".equals(categoryType)) {
                for (Record record : incomeRecords) {
                    Date recordDate = dateFormat.parse(record.date);
                    if (recordDate.equals(queryDate)) {
                        System.out.println(record);
                    }
                }
            } else if ("支出".equals(categoryType)) {
                for (Record record : expenseRecords) {
                    Date recordDate = dateFormat.parse(record.date);
                    if (recordDate.equals(queryDate)) {
                        System.out.println(record);
                    }
                }
            } else {
                System.out.println("无效的类别，请输入“收入”或“支出”。");
            }
        } catch (ParseException e) {
            System.out.println("日期格式错误，查询失败。");
        }
    }

    // 按日期范围查询账单
    private void queryByDateRange(String categoryType, String startDate, String endDate) {
        try {
            Date start = dateFormat.parse(startDate);
            Date end = dateFormat.parse(endDate);
            if ("收入".equals(categoryType)) {
                for (Record record : incomeRecords) {
                    Date recordDate = dateFormat.parse(record.date);
                    if (recordDate.compareTo(start) >= 0 && recordDate.compareTo(end) <= 0) {
                        System.out.println(record);
                    }
                }
            } else if ("支出".equals(categoryType)) {
                for (Record record : expenseRecords) {
                    Date recordDate = dateFormat.parse(record.date);
                    if (recordDate.compareTo(start) >= 0 && recordDate.compareTo(end) <= 0) {
                        System.out.println(record);
                    }
                }
            } else {
                System.out.println("无效的类别，请输入“收入”或“支出”。");
            }
        } catch (ParseException e) {
            System.out.println("日期格式错误，查询失败。");
        }
    }

    // 按类别查询账单
    private void queryByCategory(String categoryType, String category) {
        if ("收入".equals(categoryType)) {
            for (Record record : incomeRecords) {
                if (record.category.equals(category)) {
                    System.out.println(record);
                }
            }
        } else if ("支出".equals(categoryType)) {
            for (Record record : expenseRecords) {
                if (record.category.equals(category)) {
                    System.out.println(record);
                }
            }
        } else {
            System.out.println("无效的类别，请输入“收入”或“支出”。");
        }
    }//
    /////
import java.util.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;

    class Record {
        String date;     //日期
        double amount;   //金额
        String category;  //种类
        String remark;   //备注

        //构造方法创建对象
        public Record(String date, double amount, String category, String remark) {
            this.date = date;
            this.amount = amount;
            this.category = category;
            this.remark = remark;
        }

        @Override
        public String toString() {
            return "日期: " + date + ", 金额: " + amount + ", 类别: " + category + ", 备注: " + remark;
        }
    }

    class FinanceTracker {
        private ArrayList<Record> incomeRecords = new ArrayList<>();
        private ArrayList<Record> expenseRecords = new ArrayList<>();
        private Scanner scanner = new Scanner(System.in);
        private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        private Map<String, Double> monthlyBudget = new HashMap<>();//添加一个 monthlyBudget 变量来存储每个月的预算：

        public static void main(String[] args) {
            FinanceTracker manager = new FinanceTracker();
            manager.showMenu();
        }

        //菜单
        public void showMenu() {
            while (true) {
                System.out.println("=================================");
                System.out.println("欢迎使用个人账单管理系统");
                System.out.println("请选择操作：");
                System.out.println("1. 记录收入");
                System.out.println("2. 记录支出");
                System.out.println("3. 查看所有账单");
                System.out.println("4. 查询账单");
                System.out.println("5. 设置月度预算");
                System.out.println("6. 查看月度统计报告");
                System.out.println("7. 退出系统");
                System.out.print("请输入选项序号：");
                int option = scanner.nextInt();
                scanner.nextLine(); // 清除缓冲区

                switch (option) {
                    case 1:
                        recordIncome();
                        break;
                    case 2:
                        recordExpense();
                        break;
                    case 3:
                        viewAllRecords();
                        break;
                    case 4:
                        queryRecords();
                        break;
                    case 5:
                        setMonthlyBudget();
                        break;
                    case 6:
                        viewMonthlyReport();
                        break;
                    case 7:
                        System.out.println("感谢使用，系统已退出。");
                        return;
                    default:
                        System.out.println("无效的选项，请重新输入。");
                }
            }
        }
        //记录收入
        private void recordIncome() {
            System.out.println("请输入收入信息：");
            String date = getDateInput();
            double amount = getPositiveAmount("金额：");
            System.out.print("类别（如工资、奖金等）：");
            String category = scanner.nextLine();
            System.out.print("备注：");
            String remark = scanner.nextLine();

            incomeRecords.add(new Record(date, amount, category, remark));
            System.out.println("收入已成功记录！");

        }


        //记录支出
        private void recordExpense() {
            System.out.println("请输入支出信息：");
            String date = getDateInput();
            double amount = getPositiveAmount("金额：");
            System.out.print("类别（如餐饮、交通、购物等）：");
            String category = scanner.nextLine();
            System.out.print("备注：");
            String remark = scanner.nextLine();

            String month = date.substring(0, 7);

            //在 recordExpense() 方法中添加预算检查：
            if (monthlyBudget.containsKey(month)) {
                double remainingBudget = monthlyBudget.get(month);
                double totalExpenses = 0;
                for (Record record : expenseRecords) {
                    if (record.date.substring(0, 7).equals(month)) {
                        totalExpenses += record.amount;
                    }
                }
                if (totalExpenses + amount > remainingBudget) {
                    System.out.println("超出预算！继续记录？(y/n)");
                    String choice = scanner.nextLine();
                    if (!choice.equalsIgnoreCase("y")) {
                        System.out.println("记录取消。");
                        return;
                    }
                }
            }

            expenseRecords.add(new Record(date, amount, category, remark));
            System.out.println("支出已成功记录！");
        }

        private String getDateInput() {
            while (true) {
                System.out.print("日期（YYYY-MM-DD）：");
                String date = scanner.nextLine();
                if (isValidDate(date)) {
                    return date;
                } else {
                    System.out.println("日期格式无效，请重新输入。");
                }
            }
        }

        private boolean isValidDate(String date) {
            try {
                dateFormat.parse(date);
                return true;
            } catch (ParseException e) {
                return false;
            }
        }

        double getPositiveAmount(String prompt) {
            double amount = -1;
            while (amount < 0) {
                System.out.print(prompt);
                amount = scanner.nextDouble();
                scanner.nextLine(); // 清除缓冲区
                if (amount < 0) {
                    System.out.println("金额必须为正数，请重新输入。");
                }
            }
            return amount;
        }

        //查看账单
        private void viewAllRecords() {
            System.out.println("---- 收入记录 ----");
            for (Record t : incomeRecords ) {
                System.out.println("日期"+t.date + "金额" + t.amount + "类别" + t.category + "备注" + t.remark);
            }


            System.out.println("---- 支出记录 ----");
            for (Record t  :expenseRecords) {
                System.out.println("日期"+t.date + "金额" + t.amount + " 类别" + t.category + "备注" + t.remark);
            }
        }
        //查询账单
        private void queryRecords() {
            System.out.println("请输入查询类别（收入/支出）：");
            String categoryType = scanner.nextLine();
            System.out.println("请选择查询条件：");
            System.out.println("1. 按日期查询");
            System.out.println("2. 按日期范围查询");
            System.out.println("3. 按类别查询");
            int condition = scanner.nextInt();
            scanner.nextLine(); // 清除缓冲区

            switch (condition) {
                case 1:
                    System.out.print("请输入日期 (yyyy-MM-dd)：");
                    String date = scanner.nextLine();
                    queryByDate(categoryType, date);
                    break;
                case 2:
                    System.out.print("请输入开始日期 (yyyy-MM-dd)：");
                    String startDate = scanner.nextLine();
                    System.out.print("请输入结束日期 (yyyy-MM-dd)：");
                    String endDate = scanner.nextLine();
                    queryByDateRange(categoryType, startDate, endDate);
                    break;
                case 3:
                    System.out.print("请输入类别：");
                    String category = scanner.nextLine();
                    queryByCategory(categoryType, category);
                    break;
                default:
                    System.out.println("无效的查询条件，请重新选择。");
            }
        }

        // 按日期查询账单
        private void queryByDate(String categoryType, String date) {
            try {
                Date queryDate = dateFormat.parse(date);
                if ("收入".equals(categoryType)) {
                    for (Record record : incomeRecords) {
                        Date recordDate = dateFormat.parse(record.date);
                        if (recordDate.equals(queryDate)) {
                            System.out.println(record);
                        }
                    }
                } else if ("支出".equals(categoryType)) {
                    for (Record record : expenseRecords) {
                        Date recordDate = dateFormat.parse(record.date);
                        if (recordDate.equals(queryDate)) {
                            System.out.println(record);
                        }
                    }
                } else {
                    System.out.println("无效的类别，请输入“收入”或“支出”。");
                }
            } catch (ParseException e) {
                System.out.println("日期格式错误，查询失败。");
            }
        }

        // 按日期范围查询账单
        private void queryByDateRange(String categoryType, String startDate, String endDate) {
            try {
                Date start = dateFormat.parse(startDate);
                Date end = dateFormat.parse(endDate);
                if ("收入".equals(categoryType)) {
                    for (Record record : incomeRecords) {
                        Date recordDate = dateFormat.parse(record.date);
                        if (recordDate.compareTo(start) >= 0 && recordDate.compareTo(end) <= 0) {
                            System.out.println(record);
                        }
                    }
                } else if ("支出".equals(categoryType)) {
                    for (Record record : expenseRecords) {
                        Date recordDate = dateFormat.parse(record.date);
                        if (recordDate.compareTo(start) >= 0 && recordDate.compareTo(end) <= 0) {
                            System.out.println(record);
                        }
                    }
                } else {
                    System.out.println("无效的类别，请输入“收入”或“支出”。");
                }
            } catch (ParseException e) {
                System.out.println("日期格式错误，查询失败。");
            }
        }

        // 按类别查询账单
        private void queryByCategory(String categoryType, String category) {
            if ("收入".equals(categoryType)) {
                for (Record record : incomeRecords) {
                    if (record.category.equals(category)) {
                        System.out.println(record);
                    }
                }
            } else if ("支出".equals(categoryType)) {
                for (Record record : expenseRecords) {
                    if (record.category.equals(category)) {
                        System.out.println(record);
                    }
                }
            } else {
                System.out.println("无效的类别，请输入“收入”或“支出”。");
            }
        }



        private void setMonthlyBudget() {
            System.out.println("请输入预算月份（YYYY-MM）：");
            String month = scanner.nextLine();
            System.out.println("请输入预算金额：");
            double budget = getPositiveAmount("预算金额：");
            monthlyBudget.put(month, budget);
            System.out.println("月度预算设置成功！");
        }

        private void viewMonthlyReport() {
            System.out.println("请输入要统计的月份（YYYY-MM）：");
            String month = scanner.nextLine();

            double totalIncome = 0;
            Map<String, Double> incomeCategories = new HashMap<>();
            for (Record record : incomeRecords) {
                if (record.date.substring(0, 7).equals(month)) {
                    totalIncome += record.amount;
                    incomeCategories.put(record.category, incomeCategories.getOrDefault(record.category, 0.0) + record.amount);
                }
            }

            double totalExpense = 0;
            Map<String, Double> expenseCategories = new HashMap<>();
            for (Record record : expenseRecords) {
                if (record.date.substring(0, 7).equals(month)) {
                    totalExpense += record.amount;
                    expenseCategories.put(record.category, expenseCategories.getOrDefault(record.category, 0.0) + record.amount);
                }
            }

            System.out.println("---- " + month + " 月度统计报告 ----");
            System.out.println("总收入： " + totalIncome);
            System.out.println("总支出： " + totalExpense);
            System.out.println("结余： " + (totalIncome - totalExpense));

            System.out.println("\n收入分类统计：");
            for (Map.Entry<String, Double> entry : incomeCategories.entrySet()) {
                System.out.println(entry.getKey() + "： " + entry.getValue());
            }

            System.out.println("\n支出分类统计：");
            for (Map.Entry<String, Double> entry : expenseCategories.entrySet()) {
                System.out.println(entry.getKey() + "： " + entry.getValue());
            }

            System.out.println("\n按任意键返回主菜单...");
            scanner.nextLine();
        }
    }






    // 生成月度统计报告
    private Map<String, Map<String, Double>> generateMonthlyReport() {
        Map<String, Map<String, Double>> report = new HashMap<>();

        // 统计收入
        for (Record income : incomeRecords) {
            String month = income.date.substring(0, 7);
            Map<String, Double> monthData = report.computeIfAbsent(month, k -> new HashMap<>());
            monthData.put("总收入", monthData.getOrDefault("总收入", 0.0) + income.amount);
            monthData.put("收入_" + income.category, monthData.getOrDefault("收入_" + income.category, 0.0) + income.amount);
        }

        // 统计支出
        for (Record expense : expenseRecords) {
            String month = expense.date.substring(0, 7);
            Map<String, Double> monthData = report.computeIfAbsent(month, k -> new HashMap<>());
            monthData.put("总支出", monthData.getOrDefault("总支出", 0.0) + expense.amount);
            monthData.put("支出_" + expense.category, monthData.getOrDefault("支出_" + expense.category, 0.0) + expense.amount);
        }

        return report;
    }
}
}




